package com.freshmarket.freshmarket.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.freshmarket.freshmarket.controller.form.NewOrderByCarForm;
import com.freshmarket.freshmarket.controller.form.NewOrderByLimitedForm;
import com.freshmarket.freshmarket.dao.*;
import com.freshmarket.freshmarket.entity.*;
import com.freshmarket.freshmarket.exception.ArgsMistakeException;
import com.freshmarket.freshmarket.service.IOrdersService;
import com.freshmarket.freshmarket.utils.Result;
import com.freshmarket.freshmarket.utils.Utils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author Squirrel
 * @since 2020-09-04
 */
@Service
public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders> implements IOrdersService {
    final UserMapper userMapper;

    final ProductMapper productMapper;

    final OrdersMapper ordersMapper;

    final OrderInfoMapper orderInfoMapper;

    final CouponMapper couponMapper;

    final UserCouponMapper userCouponMapper;

    final OrdersLimitedTimeOfferMapper ordersLimitedTimeOfferMapper;

    final LimitedTimeOfferMapper limitedTimeOfferMapper;

    final OrdersProductBatchMapper ordersProductBatchMapper;

    final ShoppingCarMapper shoppingCarMapper;

    final UserCouponServiceImpl userCouponService;

    final ProductBatchMapper productBatchMapper;

    final TransactionMapper transactionMapper;

    public OrdersServiceImpl(UserMapper userMapper, ProductMapper productMapper, OrdersMapper ordersMapper, OrderInfoMapper orderInfoMapper, CouponMapper couponMapper, UserCouponMapper userCouponMapper, OrdersLimitedTimeOfferMapper ordersLimitedTimeOfferMapper, LimitedTimeOfferMapper limitedTimeOfferMapper, OrdersProductBatchMapper ordersProductBatchMapper, ShoppingCarMapper shoppingCarMapper, UserCouponServiceImpl userCouponService, ProductBatchMapper productBatchMapper, TransactionMapper transactionMapper) {
        this.userMapper = userMapper;
        this.productMapper = productMapper;
        this.ordersMapper = ordersMapper;
        this.orderInfoMapper = orderInfoMapper;
        this.couponMapper = couponMapper;
        this.userCouponMapper = userCouponMapper;
        this.ordersLimitedTimeOfferMapper = ordersLimitedTimeOfferMapper;
        this.limitedTimeOfferMapper = limitedTimeOfferMapper;
        this.ordersProductBatchMapper = ordersProductBatchMapper;
        this.shoppingCarMapper = shoppingCarMapper;
        this.userCouponService = userCouponService;
        this.productBatchMapper = productBatchMapper;
        this.transactionMapper = transactionMapper;
    }

    /**
     * @author Squbi
     * @date 2020/9/9 11:28
     * @Description 购物车下单
     */
    @Override
    @Transactional
    public void newOrderByCar(NewOrderByCarForm newOrderByCarForm) throws Exception {
        User user = userMapper.selectById(newOrderByCarForm.getUserId());
        if (user == null) {
            throw new ArgsMistakeException("不存在的用户");
        } else if (newOrderByCarForm.getProductId().size() == 0) {
            throw new ArgsMistakeException("当前未选择商品");
        }
        HashMap<Integer, Integer> productId = (HashMap<Integer, Integer>) newOrderByCarForm.getProductId();

        // 用于预备订单详情
        List<OrderInfo> orderInfos = new ArrayList<>();
        //batchUse批次扣除记录 用于退单
        HashMap<Integer, Integer> batchUse = new HashMap<>();

        //标记总价 开始遍历购物车的商品列表
        double totalPrice = 0.0;
        for (Integer id : productId.keySet()) {
            Product product = productMapper.selectById(id);
            if (product == null) {
                throw new ArgsMistakeException("商品id错误:" + id);
            }

            //减少购物车数量
            ShoppingCar shoppingCar = shoppingCarMapper.selectOne(new QueryWrapper<ShoppingCar>().eq("user_id", user.getUserId()).eq("product_id", product.getProductId()));
            if (shoppingCar == null) {
                throw new ArgsMistakeException("该购物车参数异常");
            }
            shoppingCar.setProductNum(0);
            shoppingCarMapper.updateById(shoppingCar);

            //扣除商品总数
            int buyNum = productId.get(id);
            if (buyNum > product.getProductNum()) {
                throw new ArgsMistakeException("商品数量不足 商品id:" + id);
            }
            product.setProductNum(product.getProductNum() - buyNum);
            productMapper.updateById(product);
            totalPrice += product.getProductPrice() * buyNum;
            OrderInfo orderInfo = new OrderInfo();

            //通过该商品找出其对应未过期批次 已按照时间由旧到新排序
            List<ProductBatch> productBatches = productBatchMapper.selectOldBatch(product.getProductId());
            int needNum = buyNum;
            for (int i = 0; i < productBatches.size(); i++) {
                ProductBatch productBatch = productBatches.get(i);
                if (productBatch == null) {
                    throw new ArgsMistakeException("批次id错误:" + i);
                }

                //如果批次拥有数量大于等于需求数量 直接更新状态并break
                if (productBatch.getProductBatchNum() >= needNum) {
                    productBatch.setProductBatchNum(productBatch.getProductBatchNum() - needNum);
                    batchUse.put(id, needNum);
                    productBatchMapper.updateById(productBatch);
                    break;
                } else {
                    //如果批次拥有数量不足 先扣除当前批次与需求数量 再往下遍历
                    needNum -= productBatch.getProductBatchNum();
                    batchUse.put(id, productBatch.getProductBatchNum());
                    productBatch.setProductBatchNum(0);
                    productBatchMapper.updateById(productBatch);
                }
            }

            //将当前已有的信息存入orderInfos 已有:小计 购买数量 商品id 还差:订单id 实际小计
            orderInfo.setOrderInfoSubtotal(product.getProductPrice() * buyNum);
            orderInfo.setProductId(product.getProductId());
            orderInfo.setProductNum(buyNum);
            orderInfos.add(orderInfo);
        }

        //用户优惠券
        HashMap<Integer, Integer> userCouponId = (HashMap<Integer, Integer>) newOrderByCarForm.getUserCouponId();
        double actualTotalPrice = totalPrice;
        for (Integer id : userCouponId.keySet()) {
            Coupon coupon = couponMapper.selectById(id);
            if (coupon == null) {
                throw new ArgsMistakeException("优惠券id错误:" + id);
            } else if (userCouponId.get(id) == null) {
                continue;
            }
            int useNum = userCouponId.get(id);
            Integer productId1 = coupon.getProductId();

            //如果购买的商品有对应的优惠券 则重新计算其价格
            if (productId.containsKey(productId1)) {
                Product product = productMapper.selectById(productId1);
                double beforePrice = product.getProductPrice() * productId.get(productId1);
                double afterPrice = coupon.getCouponDiscountsStatus().equals("直扣")
                        ? beforePrice - coupon.getCouponDiscount() * useNum > 0
                        ? beforePrice - coupon.getCouponDiscount() * useNum
                        : 0
                        : beforePrice * Math.pow(coupon.getCouponDiscount(), useNum);
                actualTotalPrice -= beforePrice;
                actualTotalPrice += afterPrice;
                userCouponService.lessUserCouponNum(user.getUserId(), id, useNum);

                //遍历orderInfos 将该商品折扣后的价格算入
                for (OrderInfo orderInfo : orderInfos) {
                    if (orderInfo.getProductId() == productId1) {
                        orderInfo.setOrderInfoSubtotalActual(orderInfo.getOrderInfoSubtotal() - (beforePrice - afterPrice));
                    }
                }
            } else if (productId1 == 0) {
                actualTotalPrice = coupon.getCouponDiscountsStatus().equals("直扣")
                        ? actualTotalPrice - coupon.getCouponDiscount() * useNum > 0
                        ? actualTotalPrice - coupon.getCouponDiscount() * useNum
                        : 0
                        : actualTotalPrice * Math.pow(coupon.getCouponDiscount(), useNum);
                userCouponService.lessUserCouponNum(user.getUserId(), id, useNum);
            }
        }

        //新增订单
        Orders orders = new Orders();
        orders.setOrdersPickupAddress(newOrderByCarForm.getOrdersPickupAddress());
        orders.setOrdersPickupPhone(newOrderByCarForm.getOrdersPickupPhone());
        orders.setOrdersPickupTime(newOrderByCarForm.getOrdersPickupTime());
        orders.setOrdersStatus("未支付");
        orders.setOrdersTotalprice(totalPrice);
        orders.setOrdersTotalpriceActual(actualTotalPrice);
        orders.setUserId(user.getUserId());
        ordersMapper.insert(orders);

        //新增子订单
        for (OrderInfo orderInfo : orderInfos) {
            orderInfo.setOrdersId(orders.getOrdersId());
            if (orderInfo.getOrderInfoSubtotalActual() == null) {
                orderInfo.setOrderInfoSubtotalActual(orderInfo.getOrderInfoSubtotal());
            }
            orderInfoMapper.insert(orderInfo);
        }

        //新增订单批次交易表
        for (Integer batchId : batchUse.keySet()) {
            OrdersProductBatch ordersProductBatch = new OrdersProductBatch();
            ordersProductBatch.setOrdersId(orders.getOrdersId());
            ordersProductBatch.setProductBatchId(batchId);
            ordersProductBatch.setOrdersProductBatchBuyNum(batchUse.get(batchId));
            ordersProductBatchMapper.insert(ordersProductBatch);
        }

        //生成交易记录表
        Transaction transaction = new Transaction();
        transaction.setUserId(user.getUserId());
        transaction.setTransactionTime(Utils.getDateTime());
        transaction.setTransactionStatus("下单");
        transaction.setOrdersId(orders.getOrdersId());
        transactionMapper.insert(transaction);
    }


    /**
     * @author Squbi
     * @date 2020/9/9 11:29
     * @Description 付款
     */
    @Override
    @Transactional
    public void payOrders(int ordersId) throws Exception {
        Orders orders = ordersMapper.selectById(ordersId);
        if (orders == null) {
            throw new ArgsMistakeException("订单不存在 订单id:" + ordersId);
        }
        User user = userMapper.selectById(orders.getUserId());
        double priceActual = orders.getOrdersTotalpriceActual();
        if (priceActual > user.getUserMoney()) {
            throw new ArgsMistakeException("用户余额不足 请先充值 当前余额:" + user.getUserMoney());
        }
        //扣钱 加分
        user.setUserMoney(user.getUserMoney() - priceActual);
        int score = (int) (priceActual / 100);
        user.setUserScore(user.getUserScore() + score);
        userMapper.updateById(user);

        //遍历结算赠送的劵 如果用户支付金额达到要求 则赠送
        List<Coupon> coupons = couponMapper.selectByCouponStatus("结算赠送");
        for (Coupon coupon : coupons) {
            if (coupon.getCouponThreshold() <= priceActual) {
                UserCoupon userCoupon = new UserCoupon();
                userCoupon.setUserCouponNum(1);
                userCoupon.setCouponId(coupon.getCouponId());
                userCoupon.setUserCouponGettime(Utils.getDate());
                userCoupon.setUserId(user.getUserId());
                userCouponMapper.insert(userCoupon);
            }
        }

        //改订单状态 生成交易记录
        orders.setOrdersStatus("已支付");
        ordersMapper.updateById(orders);

        //生成交易记录表
        Transaction transaction = new Transaction();
        transaction.setUserId(user.getUserId());
        transaction.setTransactionTime(Utils.getDateTime());
        transaction.setTransactionStatus("付款");
        transaction.setOrdersId(orders.getOrdersId());
        transactionMapper.insert(transaction);
    }

    /**
     * @author Squbi
     * @date 2020/9/9 11:29
     * @Description 秒杀下单
     */
    @Override
    @Transactional
    public void newOrderByLimited(NewOrderByLimitedForm newOrderByLimitedForm) throws Exception {
        User user = userMapper.selectById(newOrderByLimitedForm.getUserId());
        if (user == null) {
            throw new ArgsMistakeException("不存在的用户id:" + newOrderByLimitedForm.getUserId());
        }
        LimitedTimeOffer limitedTimeOffer = limitedTimeOfferMapper.selectById(newOrderByLimitedForm.getLimitedTimeOfferId());
        if (limitedTimeOffer == null) {
            throw new ArgsMistakeException("异常的limitedTimeOfferId:" + newOrderByLimitedForm.getLimitedTimeOfferId());
        }
        Integer sum = ordersLimitedTimeOfferMapper.selectCount(user.getUserId(), limitedTimeOffer.getLimitedTimeOfferId());
        if (sum!=null&&sum > limitedTimeOffer.getLimitedTimeOfferPerNum()) {
            throw new ArgsMistakeException("购买的数量超出了活动限制");
        }
        Product product = productMapper.selectById(newOrderByLimitedForm.getProductId());
        if (product == null) {
            throw new ArgsMistakeException("不存在的商品id:" + newOrderByLimitedForm.getProductId());
        }
        double price = product.getProductPrice() * newOrderByLimitedForm.getBuyNum();
        double priceActual = product.getProductPrice() * newOrderByLimitedForm.getBuyNum() * limitedTimeOffer.getLimitedTimeOfferDiscount();

        limitedTimeOffer.setLimitedTimeOfferTotalNum(limitedTimeOffer.getLimitedTimeOfferTotalNum() - newOrderByLimitedForm.getBuyNum());
        limitedTimeOffer.setLimitedTimeOfferSale(limitedTimeOffer.getLimitedTimeOfferSale() + newOrderByLimitedForm.getBuyNum());
        limitedTimeOfferMapper.updateById(limitedTimeOffer);

        Orders orders = new Orders();
        orders.setUserId(user.getUserId());
        orders.setOrdersTotalprice(price);
        orders.setOrdersTotalpriceActual(priceActual);
        orders.setOrdersStatus("未支付");
        orders.setOrdersPickupTime(newOrderByLimitedForm.getOrdersPickupTime());
        orders.setOrdersPickupPhone(newOrderByLimitedForm.getOrdersPickupPhone());
        orders.setOrdersPickupAddress(newOrderByLimitedForm.getOrdersPickupAddress());
        ordersMapper.insert(orders);

        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setOrderInfoSubtotal(price);
        orderInfo.setOrderInfoSubtotalActual(priceActual);
        orderInfo.setOrdersId(orders.getOrdersId());
        orderInfo.setProductNum(newOrderByLimitedForm.getBuyNum());
        orderInfo.setProductId(product.getProductId());
        orderInfoMapper.insert(orderInfo);
    }


    /**
     * @author Squbi
     * @date 2020/9/9 11:29
     * @Description 退货
     */
    @Override
    @Transactional
    public void rollbackOrders(int ordersId) throws Exception {
        Orders orders = ordersMapper.selectById(ordersId);
        if (orders == null) {
            throw new ArgsMistakeException("不存在的订单Id:" + ordersId);
        }
        OrdersLimitedTimeOffer ordersLimitedTimeOffer = ordersLimitedTimeOfferMapper.selectOne(new QueryWrapper<OrdersLimitedTimeOffer>().eq("orders_id", ordersId));
        if (ordersLimitedTimeOffer != null) {
            throw new ArgsMistakeException("秒杀下单不支持退回");
        }

        //遍历orderInfo 将总数量返回
        List<OrderInfo> orderInfos = orderInfoMapper.selectList(new QueryWrapper<OrderInfo>().eq("orders_id", ordersId));
        for (OrderInfo orderInfo : orderInfos) {
            Product product = productMapper.selectById(orderInfo.getProductId());
            Integer productNum = product.getProductNum();
            if (productNum == 0) {
                product.setProductStatus("已上架");
            }
            product.setProductNum(productNum + orderInfo.getProductNum());
            productMapper.updateById(product);
        }

        //遍历ordersProductBatches 将批次数量返回
        List<OrdersProductBatch> ordersProductBatches = ordersProductBatchMapper.selectList(new QueryWrapper<OrdersProductBatch>().eq("orders_id", ordersId));
        for (OrdersProductBatch ordersProductBatch : ordersProductBatches) {
            ProductBatch productBatch = productBatchMapper.selectById(ordersProductBatch.getProductBatchId());
            productBatch.setProductBatchNum(productBatch.getProductBatchNum() + ordersProductBatch.getOrdersProductBatchBuyNum());
            productBatchMapper.updateById(productBatch);
        }

        //将用户金额返回 优惠券不予返回
        User user = userMapper.selectById(orders.getUserId());
        user.setUserMoney(user.getUserMoney() + orders.getOrdersTotalpriceActual());

        //生成交易记录
        Transaction transaction = new Transaction();
        transaction.setOrdersId(orders.getOrdersId());
        transaction.setUserId(user.getUserId());
        transaction.setTransactionStatus("退货");
        transaction.setTransactionTime(Utils.getDateTime());
        transactionMapper.insert(transaction);

        //订单状态改为已退货
        orders.setOrdersStatus("已退货");
        ordersMapper.updateById(orders);
    }

    /**
     * 查询个人订单
     *
     * @param pageIndex
     * @param pageSize
     * @param userId
     * @param ordersStatus
     * @return
     * @throws Exception
     */

    @Override
    public Result selectPersonOrdersAll(int pageIndex, int pageSize, Integer userId, String ordersStatus) throws Exception {
        //条件分页
        List<Orders> orders = ordersMapper.selectPersonOrdersAll((pageIndex - 1) * pageSize, pageSize, userId, ordersStatus);

        //总条数
        int PageCount = ordersMapper.selectPageCount(userId, ordersStatus);

        Pages success = Pages.success(PageCount, pageIndex, pageSize, orders);
        return success;

    }


}
